package org.sfgeeq.framework;

import org.sfgeeq.framework.bean.Data;
import org.sfgeeq.framework.bean.Handler;
import org.sfgeeq.framework.bean.Param;
import org.sfgeeq.framework.bean.View;
import org.sfgeeq.framework.helper.BeanHelper;
import org.sfgeeq.framework.helper.ConfigHelper;
import org.sfgeeq.framework.helper.ControllerHelper;
import org.sfgeeq.framework.helper.HelperLoader;
import org.sfgeeq.framework.util.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求转发
 * loadOnStartup  容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
 *  当值为0或者大于0时，表示容器在应用启动时就加载并初始化这个servlet；
 *  当值小于0或者没有指定时，则表示容器在该servlet被选择时才会去加载。
 *  正数的值越小，该servlet的优先级越高，应用启动时就越先加载。
 *  当值相同时，容器就会自己选择顺序来加载。
 *
 *  所以：取值0,1，2，3，4，5代表的是优先级，而非启动延迟时间。
 * Created by  on 2016/8/26.
 */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException{
//        1、初始化所有的Helper(助手)类
        HelperLoader.init();
//        2、获取ServletContext对象(用户注册Servlet)
        ServletContext servletContext=servletConfig.getServletContext();
//        3、注册处理JSP的Servlet
        ServletRegistration jspServlet=servletContext.getServletRegistration("jsp");
        jspServlet.addMapping(ConfigHelper.getAppJspPath()+"*");
//        4、注册处理静态资源的默认Servlet
        ServletRegistration defaultServlet=servletContext.getServletRegistration("default");
        defaultServlet.addMapping(ConfigHelper.getAppAssetPath()+"*");
    }

    @Override
    public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
//        1、获取请求方法和请求路径
        String requestMethod=request.getMethod().toLowerCase();
        String requestPath=request.getPathInfo();
//        2、获取Action 处理器
        Handler handler= ControllerHelper.getHandler(requestMethod,requestPath);
        if(handler!=null){
//            3、获取controller类及其Bean实例
            Class<?> controllerClass=handler.getControllerClass();
            Object controllerBean= BeanHelper.getBean(controllerClass);
//            4、创建请求参数对象
            Map<String,Object> paramMap=new HashMap<String, Object>();
            Enumeration<String> paramNames=request.getParameterNames();
            while (paramNames.hasMoreElements()){
                String paramName=paramNames.nextElement();
                String paramValue=request.getParameter(paramName);
                paramMap.put(paramName,paramValue);
            }
            String body= CodecUtil.decodeURL(StreamUtil.getString(request.getInputStream()));
            if(StringUtil.isNotEmpty(body)){
                String[] parame=StringUtil.splitString(body,"&");
                if(ArrayUtil.isNotEmpty(parame)){
                    for(String p:parame){
                        String[] array=StringUtil.splitString(p,"=");
                        if(ArrayUtil.isNotEmpty(array)&& array.length==2){
                            String paramName=array[0];//获取URL地址
                            String paramValue=array[1];//获取URL地址中的参数
                            paramMap.put(paramName,paramValue);
                        }
                    }
                }
            }


            Param param=new Param(paramMap);
//            调用ACTION方法
            Method actionMethod=handler.getActionMethod();
            Object result= ReflectionUtil.invokeMethod(controllerBean,actionMethod,param);
//            处理Action方法返回值
            if(result instanceof View){
                //返回JSP页面
                View view=(View) request;
                String path=view.getPath();
                if(StringUtil.isNotEmpty(path)){
                    if(path.startsWith("/")){
                        response.sendRedirect(request.getContextPath() + path);
                    }else {
                        Map<String, Object> model = view.getModel();
                        for (Map.Entry<String, Object> entry : model.entrySet()) {
                            request.setAttribute(entry.getKey(), entry.getValue());
                        }
                        request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
                    }
                }
            }else if(result instanceof Data){
                //返回JSON数据
                Data data=(Data) result;
                Object model = data.getModel();
                if (model != null) {
                    response.setContentType("application/json");
                    response.setCharacterEncoding("UTF-8");
                    PrintWriter writer = response.getWriter();
                    String json = JsonUtil.toJson(model);
                    writer.write(json);
                    writer.flush();
                    writer.close();
                }
            }

        }

    }
}
